/**********************************************************************************************************
** 驱动文件：	ups-3C3_EX.c
** 驱动类型：	ups
** 设备名称：	山特UPS
** 设备型号：	3C3_EX
** 设备品牌：	山特
** 设备协议：	RS232通讯协议
** 驱动描述：	适用于山特3C3-EX三相UPS状态监测，协议类型为RS232C通信协议，指令为Q2<cr>、WA<cr>
** 生成日期：	2018-07-28 16:53:35
**********************************************************************************************************/
#include "Includes.h"


/**********************************************************************************************************
* 定义设备数据点变量结构
**********************************************************************************************************/
typedef struct{
	Var InputVoltageA;							//A相输入电压
	Var InputVoltageB;							//B相输入电压
	Var InputVoltageC;							//C相输入电压
	Var FaultVoltage;							//输入故障电压
	Var OutputVoltageA;							//A相输出电压
	Var OutputVoltageB;							//B相输出电压
	Var OutputVoltageC;							//C相输出电压
	Var LoadCurrentRateA;						//A相负载电流百分比
	Var LoadCurrentRateB;						//B相负载电流百分比
	Var LoadCurrentRateC;						//C相负载电流百分比
	Var InputFrequency;							//输入频率
	Var BatteryVoltage;							//电池电压
	Var Temperature;							//UPS温度
	Var UtilityFail;							//市电故障
	Var BatteryLowVoltage;						//电池欠压
	Var BypassActive;							//旁路激活
	Var UPSFailed;								//UPS故障
	Var UPSType;								//UPS类型
	Var UPSTest;								//UPS测试
	Var ShutdownActive;							//关机激活
	Var OutputPowerA;							//A相输出有功功率
	Var OutputPowerB;							//B相输出有功功率
	Var OutputPowerC;							//C相输出有功功率
	Var OutputComplexPowerA;					//A相输出视在功率
	Var OutputComplexPowerB;					//B相输出视在功率
	Var OutputComplexPowerC;					//C相输出视在功率
	Var TotalPower;								//总有功功率
	Var TotalComplexPower;						//总视在功率
	Var OutputCurrentA;							//A相输出电流
	Var OutputCurrentB;							//B相输出电流
	Var OutputCurrentC;							//C相输出电流
	Var LoadRate;								//负载率
}Data_Struct;									//定义变量结构


/**********************************************************************************************************
* 设备数据点变量属性声明
**********************************************************************************************************/
const static Var_Property_Def var_attr[] = {
	{
		FLOAT,
		0,
		READONLY,
		"InputVoltageA",
		"A相输入电压",
		"V",
		"A相输入电压",
		0,
		0,
		"A相输入电压过高",
		"A相输入电压过低",
		0,
		0
	},
	{
		FLOAT,
		0,
		READONLY,
		"InputVoltageB",
		"B相输入电压",
		"V",
		"B相输入电压",
		0,
		0,
		"B相输入电压过高",
		"B相输入电压过低",
		0,
		0
	},
	{
		FLOAT,
		0,
		READONLY,
		"InputVoltageC",
		"C相输入电压",
		"V",
		"C相输入电压",
		0,
		0,
		"C相输入电压过高",
		"C相输入电压过低",
		0,
		0
	},
	{
		FLOAT,
		0,
		READONLY,
		"FaultVoltage",
		"输入故障电压",
		"V",
		"市电输入故障电压",
		0,
		0,
		"",
		"",
		0.000,
		0.000
	},
	{
		FLOAT,
		0,
		READONLY,
		"OutputVoltageA",
		"A相输出电压",
		"V",
		"A相输出电压",
		0,
		0,
		"A相输出电压过高",
		"A相输出电压过低",
		0,
		0
	},
	{
		FLOAT,
		0,
		READONLY,
		"OutputVoltageB",
		"B相输出电压",
		"V",
		"B相输出电压",
		0,
		0,
		"B相输出电压过高",
		"B相输出电压过低",
		0,
		0
	},
	{
		FLOAT,
		0,
		READONLY,
		"OutputVoltageC",
		"C相输出电压",
		"V",
		"C相输出电压",
		0,
		0,
		"C相输出电压过高",
		"C相输出电压过低",
		0.000,
		0.000
	},
	{
		INTEGER,
		0,
		READONLY,
		"LoadCurrentRateA",
		"A相负载电流百分比",
		"%",
		"A相输出负载率",
		0,
		0,
		"A相输出负载率过高",
		"A相输出负载率过低",
		0.000,
		0.000
	},
	{
		INTEGER,
		0,
		READONLY,
		"LoadCurrentRateB",
		"B相负载电流百分比",
		"%",
		"B相输出负载率",
		0,
		0,
		"B相输出负载率过高",
		"B相输出负载率过低",
		0.000,
		0.000
	},
	{
		INTEGER,
		0,
		READONLY,
		"LoadCurrentRateC",
		"C相负载电流百分比",
		"%",
		"C相输出负载率",
		0,
		0,
		"C相输出负载率过高",
		"C相输出负载率过低",
		0.000,
		0.000
	},
	{
		FLOAT,
		0,
		READONLY,
		"InputFrequency",
		"输入频率",
		"Hz",
		"输入频率",
		0,
		0,
		"输入频率过高",
		"输入频率过低",
		0.000,
		0.000
	},
	{
		FLOAT,
		0,
		READONLY,
		"BatteryVoltage",
		"电池电压",
		"V",
		"电池电压",
		0,
		0,
		"电池电压过高",
		"电池电压过低",
		0.000,
		0.000
	},
	{
		FLOAT,
		0,
		READONLY,
		"Temperature",
		"UPS温度",
		"℃",
		"UPS温度",
		0,
		0,
		"UPS温度过高",
		"UPS温度过低",
		0.000,
		0.000
	},
	{
		OCTSTR,
		0,
		READONLY,
		"UtilityFail",
		"市电故障",
		"",
		"市电故障告警：无、故障",
		0,
		0,
		"",
		"",
		0.000,
		0.000
	},
	{
		OCTSTR,
		0,
		READONLY,
		"BatteryLowVoltage",
		"电池欠压",
		"",
		"电池欠压：无、欠压",
		0,
		0,
		"",
		"",
		0.000,
		0.000
	},
	{
		OCTSTR,
		0,
		READONLY,
		"BypassActive",
		"旁路激活",
		"",
		"旁路激活：未激活、激活",
		0,
		0,
		"",
		"",
		0.000,
		0.000
	},
	{
		OCTSTR,
		0,
		READONLY,
		"UPSFailed",
		"UPS故障",
		"",
		"UPS故障：无、故障",
		0,
		0,
		"",
		"",
		0.000,
		0.000
	},
	{
		OCTSTR,
		0,
		READONLY,
		"UPSType",
		"UPS类型",
		"",
		"UPS类型：在线式、后备式",
		0,
		0,
		"",
		"",
		0.000,
		0.000
	},
	{
		OCTSTR,
		0,
		READONLY,
		"UPSTest",
		"UPS测试",
		"",
		"UPS测试进程：测试中，无测试",
		0,
		0,
		"",
		"",
		0.000,
		0.000
	},
	{
		OCTSTR,
		0,
		READONLY,
		"ShutdownActive",
		"关机激活",
		"",
		"关机激活：无、激活",
		0,
		0,
		"",
		"",
		0.000,
		0.000
	},
	{
		FLOAT,
		0,
		READONLY,
		"OutputPowerA",
		"A相输出有功功率",
		"KW",
		"A相输出有功功率",
		0,
		0,
		"A相输出功率过高",
		"A相输出功率过低",
		0.000,
		0.000
	},
	{
		FLOAT,
		0,
		READONLY,
		"OutputPowerB",
		"B相输出有功功率",
		"KW",
		"B相输出有功功率",
		0,
		0,
		"B相输出功率过高",
		"B相输出功率过低",
		0.000,
		0.000
	},
	{
		FLOAT,
		0,
		READONLY,
		"OutputPowerC",
		"C相输出有功功率",
		"KW",
		"C相输出有功功率",
		0,
		0,
		"C相输出功率过高",
		"C相输出功率过低",
		0.000,
		0.000
	},
	{
		FLOAT,
		0,
		READONLY,
		"OutputComplexPowerA",
		"A相输出视在功率",
		"KVA",
		"A相输出视在功率",
		0,
		0,
		"A相输出视在功率过高",
		"A相输出视在功率过低",
		0.000,
		0.000
	},
	{
		FLOAT,
		0,
		READONLY,
		"OutputComplexPowerB",
		"B相输出视在功率",
		"KVA",
		"B相输出视在功率",
		0,
		0,
		"B相输出视在功率过低",
		"B相输出视在功率过高",
		0.000,
		0.000
	},
	{
		FLOAT,
		0,
		READONLY,
		"OutputComplexPowerC",
		"C相输出视在功率",
		"KVA",
		"C相输出视在功率",
		0,
		0,
		"C相输出视在功率过高",
		"C相输出视在功率过低",
		0.000,
		0.000
	},
	{
		FLOAT,
		0,
		READONLY,
		"TotalPower",
		"总有功功率",
		"KW",
		"总有功功率",
		0,
		0,
		"总功率过高",
		"总功率过低",
		0.000,
		0.000
	},
	{
		FLOAT,
		0,
		READONLY,
		"TotalComplexPower",
		"总视在功率",
		"KVA",
		"总视在功率",
		0,
		0,
		"总视在功率过高",
		"总视在功率过低",
		0.000,
		0.000
	},
	{
		FLOAT,
		0,
		READONLY,
		"OutputCurrentA",
		"A相输出电流",
		"A",
		"A相输出电流",
		0,
		0,
		"A相输出电流过高",
		"A相输出电流过低",
		0.000,
		0.000
	},
	{
		FLOAT,
		0,
		READONLY,
		"OutputCurrentB",
		"B相输出电流",
		"A",
		"B相输出电流",
		0,
		0,
		"B相输出电流过高",
		"B相输出电流过低",
		0.000,
		0.000
	},
	{
		FLOAT,
		0,
		READONLY,
		"OutputCurrentC",
		"C相输出电流",
		"A",
		"C相输出电流",
		0,
		0,
		"C相输出电流过高",
		"C相输出电流过低",
		0.000,
		0.000
	},
	{
		INTEGER,
		0,
		READONLY,
		"LoadRate",
		"负载率",
		"%",
		"负载率",
		0,
		0,
		"负载率过高",
		"负载率过低",
		0.000,
		0.000
	}
};


/**********************************************************************************************************
* 函数名称： static void cmd_fun(short index, int addr, void *data, char *cmd, short *len)
* 函数说明： 生成获取传感器数据指令
* 输入参数： 指令索引，传感器地址，变量结构体指针,以及指令缓存区指针,指令长度
* 返回参数： 无
**********************************************************************************************************/
static void cmd_fun(short index, int addr, void *data, char *cmd, short *len)
{
	switch(index)
	{
		case 0:
			*len = sprintf(cmd,"Q2\r");
			break;
		case 1:
			*len = sprintf(cmd,"WA\r");
			break;
		default:
			break;
	}
}


/**********************************************************************************************************
* 函数名称： static int parse_fun(short index, int addr, void *data, char *buf, short len)
* 函数说明： 解析传感器响应的数据，并写入数据库
* 输入参数： 解析索引,传感器地址，变量结构体指针，以及响应数据缓存取指针，响应数据长度
* 返回参数： 返回解析结果，返回0成功，返回1失败
**********************************************************************************************************/
static int parse_fun(short index, int addr, void *data, char *buf, short len)
{
	Data_Struct 	*d = (Data_Struct*)data;
	int 			i;
	buf[len] = '\0';
	if(buf!=NULL && buf[0]=='(' && len>0 && buf[len-1]=='\r')
	{	
		switch(index)
		{
			case 0:
				for(i=0; buf[i]!='\0'; i++)
				{
					if(buf[i]=='-') buf[i]='0';
				}
				d->InputVoltageA.value.fnum 	= atof(buf+1);
				d->InputVoltageB.value.fnum 	= atof(buf+7);
				d->InputVoltageC.value.fnum 	= atof(buf+13);
				
				d->FaultVoltage.value.fnum		= atof(buf+19);
				
				d->OutputVoltageA.value.fnum 	= atof(buf+25);
				d->OutputVoltageB.value.fnum 	= atof(buf+31);
				d->OutputVoltageC.value.fnum 	= atof(buf+37);
				
				d->LoadCurrentRateA.value.fnum	= atoi(buf+43);
				d->LoadCurrentRateB.value.fnum	= atoi(buf+47);
				d->LoadCurrentRateC.value.fnum	= atoi(buf+51);
				
				d->InputFrequency.value.fnum	= atof(buf+55);
				d->BatteryVoltage.value.fnum	= atof(buf+60);
				d->Temperature.value.fnum		= atof(buf+66);
				
				d->UtilityFail.value.str		= buf[71]=='1'?"故障":"无";
				Set_Var_Status(&d->UtilityFail,	buf[71]=='1'?Alarm:Normal, NULL);	
				
				d->BatteryLowVoltage.value.str	= buf[72]=='1'?"低压":"正常";
				Set_Var_Status(&d->BatteryLowVoltage, buf[72]=='1'?Alarm:Normal, NULL);
				
				d->BypassActive.value.str		= buf[73]=='1'?"激活":"未激活";
				Set_Var_Status(&d->BypassActive,buf[73]=='1'?Normal:Alarm, NULL);
				
				d->UPSFailed.value.str			= buf[74]=='1'?"故障":"无";
				Set_Var_Status(&d->UPSFailed,	buf[74]=='1'?Alarm:Normal, NULL);	
				
				d->UPSType.value.str			= buf[75]=='1'?"后备式":"在线式";
				Set_Var_Status(&d->UPSType,		buf[75]=='1'?Alarm:Normal, NULL);
				
				d->UPSTest.value.str			= buf[76]=='1'?"测试中":"无测试";
				Set_Var_Status(&d->UPSTest,		buf[76]=='1'?Alarm:Normal, NULL);
				
				d->ShutdownActive.value.str		= buf[77]=='1'?"激活":"无";	
				Set_Var_Status(&d->ShutdownActive, buf[77]=='1'?Alarm:Normal, NULL);
				break;
			case 1:
				buf[70] ='\0';
				for(i=0; buf[i]!='\0'; i++)
				{
					if(buf[i]=='-') buf[i]='0';
				}
				d->OutputPowerA.value.fnum			= atof(buf+1);
				d->OutputPowerB.value.fnum			= atof(buf+7);
				d->OutputPowerC.value.fnum			= atof(buf+13);
				d->OutputComplexPowerA.value.fnum	= atof(buf+19);
				d->OutputComplexPowerB.value.fnum	= atof(buf+25);
				d->OutputComplexPowerC.value.fnum	= atof(buf+31);
				d->TotalPower.value.fnum			= atof(buf+37);
				d->TotalComplexPower.value.fnum		= atof(buf+43);			
				d->OutputCurrentA.value.fnum		= atof(buf+49);
				d->OutputCurrentB.value.fnum		= atof(buf+55);
				d->OutputCurrentC.value.fnum		= atof(buf+61);				
				d->LoadRate.value.inum				= atoi(buf+67);		
				break;	
			default:
				break;
		}
		return 0;
	}
	return 1;
}


/**********************************************************************************************************
* 函数名称： void ups_3C3_EX_Registration(void)
* 函数说明： 山特UPS驱动注册
* 输入参数： 无
* 返回参数： 无
**********************************************************************************************************/
void ups_3C3_EX_Registration(void)
{	
	DeviceDriverRegistration(
		"ups",													//设备类型
		"山特UPS",												//设备名称（导航栏默认显示名称）
		"山特",													//品牌名称
		"3C3_EX",												//设备型号
		"适用于山特3C3-EX三相UPS状态监测，协议类型为RS232C通信协议，指令为Q2<cr>、WA<cr>",//驱动描述
		var_attr,												//变量属性声明
		sizeof(Data_Struct),									//变量结构体空间大小
		cmd_fun,												//发送指令生成函数
		parse_fun,												//数据解析函数
		600														//设备响应超时时间
	);
		
#if 0
	#define	CMD1	"Q2\r"
	#define	RSP1	"(234.3 234.0 234.3 140.0 234.7 234.3 234.1 000 000 000 49.9 000.0 25.0 00100000 000.00 000 00 00 00 00 00 00104000 11\r"
	#define	CMD2	"WA\r"
	#define	RSP2	"(000.0 000.0 000.0 000.0 000.2 000.1 000.0 004.6 000.3 000.8 000.5 000 00100000\r"
	VirtualFrameRegistration(CMD1, sizeof(CMD1)-1, RSP1, sizeof(RSP1)-1);
	VirtualFrameRegistration(CMD2, sizeof(CMD2)-1, RSP2, sizeof(RSP2)-1);					
#endif	
}

